package com.zwb.demo.easyweb.modules.genCode;

import com.zwb.demo.easyweb.common.entity.response.CommonCode;
import com.zwb.demo.easyweb.common.entity.response.ResponseResult;
import com.zwb.demo.easyweb.core.exception.ExceptionCast;
import com.zwb.demo.easyweb.modules.config.entity.GenTemplateFilePO;
import com.zwb.demo.easyweb.modules.config.entity.GenTemplatePO;
import com.zwb.demo.easyweb.modules.config.entity.JavaFieldTypePO;
import com.zwb.demo.easyweb.modules.config.repository.GenTemplateFilePoRepository;
import com.zwb.demo.easyweb.modules.config.repository.GenTemplatePoRepository;
import com.zwb.demo.easyweb.modules.config.repository.JavaFieldTypePORepository;
import com.zwb.demo.easyweb.modules.database.entity.DatabaseColumnPO;
import com.zwb.demo.easyweb.modules.database.entity.DatabaseTablePO;
import com.zwb.demo.easyweb.modules.database.repository.DatabaseColumnPORepository;
import com.zwb.demo.easyweb.modules.database.repository.DatabaseLinkPORepository;
import com.zwb.demo.easyweb.modules.database.repository.DatabaseTablePORepository;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.Cleanup;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Service
public class GenCodeServiceImpl implements GenCodeService {
    private final GenTemplatePoRepository genTemplateRepository;
    private final GenTemplateFilePoRepository genTemplateFileRepository;
    private final DatabaseTablePORepository databaseTableRepository;
    private final DatabaseLinkPORepository databaseLinkRepository;
    private final DatabaseColumnPORepository databaseColumnRepository;
    private final JavaFieldTypePORepository javaFieldTypeRepository;

    @Autowired
    public GenCodeServiceImpl(
            GenTemplatePoRepository genTemplateRepository,
            GenTemplateFilePoRepository genTemplateFileRepository,
            DatabaseTablePORepository databaseTableRepository,
            DatabaseLinkPORepository databaseLinkRepository,
            DatabaseColumnPORepository databaseColumnRepository,
            JavaFieldTypePORepository javaFieldTypeRepository) {
        this.genTemplateRepository = genTemplateRepository;
        this.genTemplateFileRepository = genTemplateFileRepository;
        this.databaseTableRepository = databaseTableRepository;
        this.databaseLinkRepository = databaseLinkRepository;
        this.databaseColumnRepository = databaseColumnRepository;
        this.javaFieldTypeRepository = javaFieldTypeRepository;
    }

    @SneakyThrows
    @Override
    public ResponseResult genCode(GenCodeVO genCodeVO) {
        if (StringUtils.isBlank(genCodeVO.getTemplateType())
                || StringUtils.isBlank(genCodeVO.getDatabaseTableId())) {
            ExceptionCast.cast(CommonCode.ILLEGAL_PARAM);
        }

        Optional<DatabaseTablePO> tableOptional =
                databaseTableRepository.findById(genCodeVO.getDatabaseTableId());
        if (!tableOptional.isPresent()) {
            ExceptionCast.cast(GenCodeCode.TABLE_ID_NO_EXITS);
        }
        DatabaseTablePO tablePO = tableOptional.get();
        // 组装数据
        DefinitionTable definitionTable = new DefinitionTable();
        definitionTable.setGenerateDate(LocalDateTime.now().toString());
        BeanUtils.copyProperties(genCodeVO, definitionTable);
        BeanUtils.copyProperties(tablePO, definitionTable);

        List<DatabaseColumnPO> columns =
                databaseColumnRepository.findAllByTableId(genCodeVO.getDatabaseTableId());
        for (DatabaseColumnPO column : columns) {
            DefinitionColumn definitionColumn = new DefinitionColumn();
            BeanUtils.copyProperties(column, definitionColumn);
            // java类型
            Optional<JavaFieldTypePO> columnOptional =
                    javaFieldTypeRepository.findById(definitionColumn.getJavaType());
            if (!columnOptional.isPresent()) {
                ExceptionCast.cast(GenCodeCode.JAVA_FIELD_ID_NO_EXITS);
            }
            JavaFieldTypePO javaFieldTypePO = columnOptional.get();
            definitionColumn.setJavaLabel(javaFieldTypePO.getLabel());
            if (!javaFieldTypePO.getBasicType()) {
                definitionTable.getJavaImports().add(javaFieldTypePO.getClassName());
            }
            definitionTable.getColumns().add(definitionColumn);
        }
        // 获取模板
        Optional<GenTemplatePO> templateOptional =
                genTemplateRepository.findById(genCodeVO.getTemplateType());
        if (!templateOptional.isPresent()) {
            ExceptionCast.cast(GenCodeCode.TEMPLATE_ID_NO_EXITS);
        }
        List<GenTemplateFilePO> templateList =
                genTemplateFileRepository.findAllByTemplateId(genCodeVO.getTemplateType());
        for (GenTemplateFilePO templateFile : templateList) {
            if (StringUtils.isBlank(templateFile.getContents())) {
                ExceptionCast.cast(GenCodeCode.TEMPLATE_CONTENTS_NULL);
            }
            Template t =
                    new Template(
                            "template",
                            new StringReader(templateFile.getContents()),
                            new Configuration(Configuration.VERSION_2_3_23));
            File outFile =
                    new File(
                            genCodeVO.getJavaGeneratePath()
                                    + "/"
                                    + definitionTable.getClassName()
                                    + templateFile.getFileName());
            @Cleanup
            Writer  out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
            // 生成代码
            t.process(definitionTable, out);
            out.flush();
        }
        return ResponseResult.ok();
    }
}
